home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 August (Alt) / CHIP 2005-08.1.iso / program / guvenlik / syslinux-3.07.exe / libfat / fatchain.c < prev    next >
Encoding:
C/C++ Source or Header  |  2004-12-15  |  3.4 KB  |  137 lines

  1. #ident "$Id: fatchain.c,v 1.1 2004/12/15 10:14:39 hpa Exp $"
  2. /* ----------------------------------------------------------------------- *
  3.  *   
  4.  *   Copyright 2004 H. Peter Anvin - All Rights Reserved
  5.  *
  6.  *   This program is free software; you can redistribute it and/or modify
  7.  *   it under the terms of the GNU General Public License as published by
  8.  *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  9.  *   Boston MA 02111-1307, USA; either version 2 of the License, or
  10.  *   (at your option) any later version; incorporated herein by reference.
  11.  *
  12.  * ----------------------------------------------------------------------- */
  13.  
  14. /*
  15.  * fatchain.c
  16.  *
  17.  * Follow a FAT chain
  18.  */
  19.  
  20. #include "libfatint.h"
  21. #include "ulint.h"
  22.  
  23. /*
  24.  * Convert a cluster number (or 0 for the root directory) to a
  25.  * sector number.  Return -1 on failure.
  26.  */
  27. libfat_sector_t libfat_clustertosector(const struct libfat_filesystem *fs,
  28.                        int32_t cluster)
  29. {
  30.   if ( cluster == 0 )
  31.     cluster = fs->rootcluster;
  32.  
  33.   if ( cluster == 0 )
  34.     return fs->rootdir;
  35.   else if ( cluster < 2 || cluster >= fs->endcluster )
  36.     return -1;
  37.   else
  38.     return fs->data + ((libfat_sector_t)(cluster-2) << fs->clustshift);
  39. }
  40.  
  41. /*
  42.  * Get the next sector of either the root directory or a FAT chain.
  43.  * Returns 0 on end of file and -1 on error.
  44.  */
  45.  
  46. libfat_sector_t libfat_nextsector(struct libfat_filesystem *fs,
  47.                   libfat_sector_t s)
  48. {
  49.   int32_t cluster, nextcluster;
  50.   uint32_t fatoffset;
  51.   libfat_sector_t fatsect;
  52.   uint8_t *fsdata;
  53.   uint32_t clustmask = fs->clustsize - 1;
  54.   libfat_sector_t rs;
  55.  
  56.   if ( s < fs->data ) {
  57.     if ( s < fs->rootdir )
  58.       return -1;
  59.  
  60.     /* Root directory */
  61.     s++;
  62.     return ( s < fs->data ) ? s : 0;
  63.   }
  64.  
  65.   rs = s - fs->data;
  66.  
  67.   if ( ~rs & clustmask )
  68.     return s+1;            /* Next sector in cluster */
  69.  
  70.   cluster = 2 + (rs >> fs->clustshift);
  71.  
  72.   if ( cluster >= fs->endcluster )
  73.     return -1;
  74.  
  75.   switch ( fs->fat_type ) {
  76.   case FAT12:
  77.     /* Get first byte */
  78.     fatoffset = cluster + (cluster >> 1);
  79.     fatsect = fs->fat + (fatoffset >> LIBFAT_SECTOR_SHIFT);
  80.     fsdata = libfat_get_sector(fs, fatsect);
  81.     if ( !fsdata )
  82.       return -1;
  83.     nextcluster = fsdata[fatoffset & LIBFAT_SECTOR_MASK];
  84.  
  85.     /* Get second byte */
  86.     fatoffset++;
  87.     fatsect = fs->fat + (fatoffset >> LIBFAT_SECTOR_SHIFT);
  88.     fsdata = libfat_get_sector(fs, fatsect);
  89.     if ( !fsdata )
  90.       return -1;
  91.     nextcluster |= fsdata[fatoffset & LIBFAT_SECTOR_MASK] << 8;
  92.  
  93.     /* Extract the FAT entry */
  94.     if ( cluster & 1 )
  95.       nextcluster >>= 4;
  96.     else
  97.       nextcluster &= 0x0FFF;
  98.  
  99.     if ( nextcluster >= 0x0FF8 )
  100.       return 0;
  101.     break;
  102.  
  103.   case FAT16:
  104.     fatoffset = cluster << 1;
  105.     fatsect = fs->fat + (fatoffset >> LIBFAT_SECTOR_SHIFT);
  106.     fsdata = libfat_get_sector(fs, fatsect);
  107.     if ( !fsdata )
  108.       return -1;
  109.     nextcluster = read16((le16_t *)&fsdata[fatoffset & LIBFAT_SECTOR_MASK]);
  110.     
  111.     if ( nextcluster >= 0x0FFF8 )
  112.       return 0;
  113.     break;
  114.  
  115.   case FAT28:
  116.     fatoffset = cluster << 2;
  117.     fatsect = fs->fat + (fatoffset >> LIBFAT_SECTOR_SHIFT);
  118.     fsdata = libfat_get_sector(fs, fatsect);
  119.     if ( !fsdata )
  120.       return -1;
  121.     nextcluster = read32((le32_t *)&fsdata[fatoffset & LIBFAT_SECTOR_MASK]);
  122.     nextcluster &= 0x0FFFFFFF;
  123.     
  124.     if ( nextcluster >= 0x0FFFFFF8 )
  125.       return 0;
  126.     break;
  127.     
  128.   default:
  129.     return -1;            /* WTF? */
  130.   }
  131.  
  132.   return libfat_clustertosector(fs, nextcluster);
  133. }
  134.  
  135.     
  136.  
  137.